package jonaVisual;

import java.awt.Rectangle;

import Jona.*;
import java.awt.*;
import java.util.Vector;


public class VOTreeMaker3 {
	private VisualObject[] vo1;
	private final int xOffset = 5;
	private final int yOffset = 5;
	private final int minimumstatementHeight = 40;
	private int nextRow = 0;
	private int initIndent = 0;
	private int horizontalSpacer = 25;
	private int nextRowIndent = 5; //actually 5..
	private int minx = 100;
	
	public VisualObject[] makeTreeFromTheory(Theory t1)
	{
		long time = System.currentTimeMillis();
		ArgObject[] roots = t1.giveRootStatements();
		ArgObject[] statements = t1.getStatements();
		vo1 = null;	
		if(roots != null)
		{
			if(roots.length > 0)
			{
				for(int i =0; i < roots.length ; i++)
				{
					makeTreeForStatement(null,roots[i],statements,initIndent,null,true, new Vector(5),false);
				}
				
				//System.out.println("MINX=" + minx);
				minx-= 10;
				for(int i =0; i < vo1.length; i++)
				{
					vo1[i].translate(-minx,0);
				}
			}
		}
		System.out.println("made Tree in : " + (System.currentTimeMillis() - time) + " millisecs.");
		
		
		return vo1;
	}
	
	
	
	private void makeTreeForStatement(ArgObject root,ArgObject statement, ArgObject[] statements, int indent, Point pointTo, boolean horizontal, Vector done,boolean negate)
	{
		int first = 1;
		int second = 0;
		
		if(statement instanceof Conditional)
		{
			ArgObject[][] attacksupport = getAttackerAndSupporters(statement,statements);
			Conditional c1 = (Conditional)statement;
			int total =  attacksupport[0].length + attacksupport[1].length;
			
			if(horizontal)
			{
				int yCoor = yOffset+ nextRow;
				for(int i =0; i < attacksupport[first].length; i++)
				{
					makeTreeForStatement(statement,attacksupport[first][i],statements,indent,new Point(xOffset + indent,yOffset+ nextRow), !horizontal,new Vector(done),negate);
					
				}
				
				for(int i =0; i < attacksupport[second].length; i++)
				{
					makeTreeForStatement(statement,attacksupport[second][i],statements,indent,new Point(xOffset + indent,yOffset+ nextRow),!horizontal,new Vector(done),negate);
				}
				
				for(int i = 0; i < c1.getAntecedents().length; i++)
				{
					makeTreeForStatement(statement,c1.getAntecedents()[i],statements,indent,pointTo,horizontal,new Vector(done),negate);
				}
			}
			else
			{
				int yCoor = yOffset + nextRow + 20;
				int lineIndentX = (total * horizontalSpacer);
				if(lineIndentX < horizontalSpacer) lineIndentX = horizontalSpacer;
				for(int i = 0; i < c1.getAntecedents().length; i++)
				{
					makeTreeForStatement(statement,c1.getAntecedents()[i],statements,indent + lineIndentX ,pointTo,horizontal,new Vector(done),negate);
				}	
				indent += (total * horizontalSpacer);
				
				for(int i =0; i < attacksupport[first].length; i++)
				{
					makeTreeForStatement(statement,attacksupport[first][i],statements,indent,new Point(xOffset + indent,yCoor), !horizontal,new Vector(done),negate);
					indent-=horizontalSpacer;
					
				}
				
				for(int i =0; i < attacksupport[second].length; i++)
				{
					makeTreeForStatement(statement,attacksupport[second][i],statements,indent,new Point(xOffset + indent,yCoor),!horizontal,new Vector(done),negate);
					indent-=horizontalSpacer;
				}
			}		
		}
		else
		{
			ArgObject[][] attacksupport = getAttackerAndSupporters(statement,statements);
			int total = attacksupport[0].length + attacksupport[1].length;
			
			if(pointTo != null && (root instanceof Conditional))
			{
				Arrow  a1= new Arrow((Conditional)root);
				a1.addPoint(xOffset + indent, yOffset+ nextRow+20);
				if(minx > (xOffset + indent)) minx = (xOffset + indent);
				if(horizontal)
				{
					a1.addPoint(pointTo.x - 15, yOffset+ nextRow+20);
					a1.addPoint(pointTo.x - 15,pointTo.y );
				}
				else
				{
					a1.addPoint(pointTo.x - 15,pointTo.y + 20);
				}
				if(minx > (pointTo.x - 15)) minx = (pointTo.x - 15);
				addVisualObject(a1);	
			}
			
			
			boolean found = false;
			int j =0;
			while(j < done.size() && !found)
			{
				if(done.get(j) == statement)
					found = true;
				j++;
			}
			
				done.add(statement);
			
				VisualArgObject va1 = new VisualArgObject(statement);
				va1.setRecursive(found);
				int statementHeight = 0;
				String data[] = statement.getText().split("\n");
				if(data.length > 1)
				{
					statementHeight = ((data.length - 1) * 10) + 20;
				}
			
				if(statementHeight < minimumstatementHeight) statementHeight = minimumstatementHeight;
				
				int xpos = xOffset + indent;
				
				if(negate)
				{
					xpos = xOffset - total*horizontalSpacer + 10 ;
				}
				va1.setRectangle(new Rectangle(xpos,yOffset + nextRow,total*horizontalSpacer + 10,statementHeight));	
				
			
				nextRow+= nextRowIndent + statementHeight;
				if(minx > xpos) minx = xpos;
				addVisualObject(va1);
				
			if(!found)
			{	
				indent += (total * horizontalSpacer) + 10;
				int yCoor = yOffset + nextRow - nextRowIndent;
				horizontal = true;
				for(int i =0; i < attacksupport[first].length; i++)
				{
					makeTreeForStatement(statement,attacksupport[first][i],statements, indent , new Point(xOffset + indent,yCoor),horizontal,new Vector(done),false);
					indent-=horizontalSpacer;
				}
				indent -=  horizontalSpacer;
				//indent -=(total * horizontalSpacer) + 10;
				for(int i =0; i < attacksupport[second].length; i++)
				{
					makeTreeForStatement(statement,attacksupport[second][i],statements, indent, new Point(xOffset + indent, yCoor),horizontal,new Vector(done),true);
					indent+=horizontalSpacer;
				}
			}		
			else
			{
				if((root instanceof Conditional))
				{
					Conditional c1 = (Conditional)root;
					c1.setAntecedent_isRecursive(true);
				}
				System.out.println("recursive path found!");
			}
		}
	}
	
	private ArgObject[][] getAttackerAndSupporters(ArgObject root, ArgObject[] statements)
	{
		ArgObject[][] attacksupport = new ArgObject[2][0];
		
		for(int i =0 ; i < statements.length; i++)
		{
			if(statements[i] instanceof Conditional)
			{
				Conditional c1 = (Conditional)statements[i];
				if(c1.getConsequent() instanceof Negation)
				{
					Negation n1 = (Negation)c1.getConsequent();
					if(n1.getNegation() == root)
						attacksupport[0] = addToList(attacksupport[0],c1);	
				}
				else
				{
					if(c1.getConsequent() == root)
						attacksupport[1] = addToList(attacksupport[1],c1);
				}
			}
		}
		
		return attacksupport;
	}
	
	protected ArgObject [] addToList(ArgObject [] list, ArgObject element) {
		if(list == null)  
		{
			list = new ArgObject[1];
			list[0] = element;
			return list;
		}
		else
		{
			int i, length;
			ArgObject [] temp;
			
			length = list.length;
			
			temp = new ArgObject[length+1];
			for (i = 0; i < length; ++i) {
				if (list[i] == element) {
					return list;
				}
				temp[i] = list[i];
			}
			temp[length] = element;
			return temp;
		}
	}
	
	protected boolean findInList(ArgObject[] list, ArgObject element)
	{
		boolean found = false;
		int i =0;
		while(!found && i < list.length)
		{
			if(list[i]== element) found = true;
			i++;
		}
		return found;
	}	
	
	private void addVisualObject(VisualObject vo2)
	{
		if(vo1 == null)
		{	
			vo1 = new VisualObject[1];
			vo1[0] = vo2;				
		}
		else
		{
			VisualObject[] dum = new VisualObject[vo1.length + 1];
			for(int i =0; i < vo1.length;i++)
				dum[i] = vo1[i];
			dum[vo1.length] = vo2;
			vo1 = dum;
		}
	}	
	
	
}
